package cn.kivensoft.util;

/** 各种类型与byte[]互转
 * @author kiven lee
 * @version 1.1
 */
final public class ConvertBytes {
	private ConvertBytes() {}

	@FunctionalInterface
	public interface ToBytes {
		void accept(byte value, int pos);
	}

	/** short写入dst, 将写入2个字节, 调用前确保空间足够
	 * @param src 要写入的值
	 * @param dst 目标数组
	 * @param pos 写入起始位置
	 */
	public static void shortToBytes(short src, byte[] dst, int pos) {
		dst[pos] = (byte) ((src >> 8) & 0xff);
		dst[pos + 1] = (byte) (src & 0xff);
	}

	/** short转成byte, 通过回调接口完成, 共调用2次回调接口
	 * @param src 要转换的值
	 * @param func 回调接口
	 */
	public static void shortToBytes(short src, ToBytes func) {
		func.accept((byte) ((src >> 8) & 0xff), 0);
		func.accept((byte) (src & 0xff), 1);
	}

	/** int写入dst, 将写入4个字节, 调用前确保空间足够
	 * @param src 要写入的值
	 * @param dst 目标数组
	 * @param pos 写入起始位置
	 */
	public static void intToBytes(int src, byte[] dst, int pos) {
		for (int shift = 24; shift >= 0; shift -= 8, ++pos)
			dst[pos] = (byte) ((src >> shift) & 0xff);
	}

	/** int转成byte, 通过回调接口完成, 共调用4次回调接口
	 * @param src 要转换的值
	 * @param func 回调接口
	 */
	public static void intToBytes(int src, ToBytes func) {
		for (int i = 0, shift = 24; shift >= 0; ++i, shift -= 8) {
			func.accept((byte) ((src >> shift) & 0xff), i);
		}
	}

	/** long写入dst, 将写入8个字节, 调用前确保空间足够
	 * @param src 要写入的值
	 * @param dst 目标数组
	 * @param pos 写入起始位置
	 */
	public static void longToBytes(long src, byte[] dst, int pos) {
		for (int shift = 56; shift >= 0; shift -= 8, ++pos)
			dst[pos] = (byte) ((src >> shift) & 0xff);
	}

	/** long转成byte, 通过回调接口完成, 共调用8次回调接口
	 * @param src 要转换的值
	 * @param func 回调接口
	 */
	public static void longToBytes(long src, ToBytes func) {
		for (int i = 0, shift = 56; shift >= 0; ++i, shift -= 8) {
			func.accept((byte) ((src >> shift) & 0xff), i);
		}
	}

	/** float写入dst, 将写入4个字节, 调用前确保空间足够
	 * @param src 要写入的值
	 * @param dst 目标数组
	 * @param pos 写入起始位置
	 */
	public static void floatToBytes(float src, byte[] dst, int pos) {
		floatToBytes(src, (v, i) -> dst[pos + i] = v);
	}

	/** float转成byte, 通过回调接口完成, 共调用4次回调接口
	 * @param src 要转换的值
	 * @param func 回调接口
	 */
	public static void floatToBytes(float src, ToBytes func) {
		intToBytes(Float.floatToIntBits(src), func);
	}

	/** double写入dst, 将写入8个字节, 调用前确保空间足够
	 * @param src 要写入的值
	 * @param dst 目标数组
	 * @param pos 写入起始位置
	 */
	public static void doubleToBytes(double src, byte[] dst, int pos) {
		doubleToBytes(src, (v, i) -> dst[pos + i] = v);
	}

	/** double转成byte, 通过回调接口完成, 共调用8次回调接口
	 * @param src 要转换的值
	 * @param func 回调接口
	 */
	public static void doubleToBytes(double src, ToBytes func) {
		longToBytes(Double.doubleToLongBits(src), func);
	}

	@FunctionalInterface
	public interface FromBytes {
		/** 读取byte的回调接口
		 * @param pos 读取位置
		 * @return 读取的byte
		 */
		byte apply(int pos);
	}

	/** byte转short, 将读取2个字节, 调用前确保空间足够
	 * @param src 源数组
	 * @param pos 读取起始位置
	 * @return 返回读取的short值
	 */
	public static short bytesToShort(byte[] src, int pos) {
		return (short) (((src[pos] & 0xFF) << 8) | (src[pos + 1] & 0xFF));
	}

	/** byte转成short, 通过回调接口完成, 共调用2次回调接口
	 * @param func 获取byte的回调接口
	 * @return 转换后的结果
	 */
	public static short bytesToShort(FromBytes func) {
		return (short) (((func.apply(0) & 0xFF) << 8) | (func.apply(1) & 0xFF));
	}

	/** byte转int, 将读取4个字节, 调用前确保空间足够
	 * @param src 源数组
	 * @param pos 读取起始位置
	 * @return 返回读取的int值
	 */
	public static int bytesToInt(byte[] src, int pos) {
		int ret = 0;
		for (int shift = 24; shift >= 0; shift -=8, ++pos)
			ret |= (src[pos] & 0xFF) << shift;
		return ret;
	}

	/** byte转成int, 通过回调接口完成, 共调用4次回调接口
	 * @param func 获取byte的回调接口
	 * @return 转换后的结果
	 */
	public static int bytesToInt(FromBytes func) {
		int ret = 0;
		for (int shift = 24, pos = 0; shift >= 0; shift -=8, ++pos)
			ret |= (func.apply(pos) & 0xFF) << shift;
		return ret;
	}

	/** byte转long, 将读取8个字节, 调用前确保空间足够
	 * @param src 源数组
	 * @param pos 读取起始位置
	 * @return 返回读取的long值
	 */
	public static long bytesToLong(byte[] src, int pos) {
		long ret = 0;
		for (int shift = 56; shift >= 0; shift -=8, ++pos)
			ret |= (src[pos] & 0xFFL) << shift;
		return ret;
	}

	/** byte转成long, 通过回调接口完成, 共调用8次回调接口
	 * @param func 获取byte的回调接口
	 * @return 转换后的结果
	 */
	public static long bytesToLong(FromBytes func) {
		long ret = 0;
		for (int shift = 56, pos = 0; shift >= 0; shift -=8, ++pos)
			ret |= (func.apply(pos) & 0xFFL) << shift;
		return ret;
	}

	/** byte转float, 将读取4个字节, 调用前确保空间足够
	 * @param src 源数组
	 * @param pos 读取起始位置
	 * @return 返回读取的float值
	 */
	public static float bytesToFloat(byte[] src, int pos) {
		return Float.intBitsToFloat(bytesToInt(src, pos));
	}

	/** byte转成float, 通过回调接口完成, 共调用4次回调接口
	 * @param func 获取byte的回调接口
	 * @return 转换后的结果
	 */
	public static float bytesToFloat(FromBytes func) {
		return Float.intBitsToFloat(bytesToInt(func));
	}

	/** byte转double, 将读取8个字节, 调用前确保空间足够
	 * @param src 源数组
	 * @param pos 读取起始位置
	 * @return 返回读取的double值
	 */
	public static double bytesToDouble(byte[] src, int pos) {
		return Double.longBitsToDouble(bytesToLong(src, pos));
	}

	/** byte转成double, 通过回调接口完成, 共调用8次回调接口
	 * @param func 获取byte的回调接口
	 * @return 转换后的结果
	 */
	public static double bytesToDouble(FromBytes func) {
		return Double.longBitsToDouble(bytesToLong(func));
	}

	/** int转long
	 * @param high 高位int
	 * @param low 低位int
	 * @return 返回转换后的long值
	 */
	public static long intsToLong(int high, int low) {
		return ((long)high << 32) | ((long)low & 0xFFFFFFFFL);
	}

	/** long写入int数组, 将写入2个int, 调用前确保空间足够
	 * @param src 源
	 * @param dst 目标数组
	 * @param pos 写入起始位置
	 */
	public static void longtoInts(long src, int[] dst, int pos) {
		dst[pos] = (int)(src >> 32 & 0xFFFFFFFFL);
		dst[pos + 1] = (int)(src &0xFFFFFFFFL);
	}

}
